<?php

require_once('lib/xmlrpc.inc');

define(LJ_URL, "www.livejournal.com");
define(XML_RPC_INTERFACE, "/interface/xmlrpc");
define(LJ_PORT, 80);

class LJItem {
	public $id = -1;
	public $eventtime;
	public $security;
	public $allowmask;
	public $subject;
	public $event;
	public $anum = -1;
	public $url = '';
	public $poster;
	public $props;

	public function isEmpty() {
		if ($this->id > 0)
		return false;
		else
		return true;
	}

	public function isFull() {
		if ($this->id > 0 && $this->anum > 0 && $this->url != '')
		return true;
		else
		return false;
	}

	public function __toString() {
		return "LJ item, id:{$this->id}, anum: {$this->anum}, subject: {$this->subject}, url: {$this->url}";
	}
}

class LJClient{
	private $username = '';
	private $password = '';

	public function LJClient($username, $password) {
		$this->setUsername($username);
		$this->setPassword($password);
		$this->client = new xmlrpc_client(XML_RPC_INTERFACE, LJ_URL, LJ_PORT);
	}

	public function getUsername() {
		return $username;
	}

	public function setUsername($username) {
		$this->username = $username;
	}

	public function getPassword() {
		return $password;
	}

	public function setPassword($password) {
		$this->password = $password;
	}

	/**
	 * The most important mode, this is how a user actually submits a new log entry to the server.
	 * @param $subject The subject of the new post
	 * @param $text The content of the new post
	 * @return the text string with the item id, anum value and url of the new post item
	 */
	public function postEvent($subject, $text) {
		$m = new xmlrpcmsg('LJ.XMLRPC.postevent', array(new xmlrpcval(
		array(
		"username" => new xmlrpcval($this->username, "string"),
		"password" => new xmlrpcval($this->password, "string"),
		"event" => new xmlrpcval($text, "string"),
		"subject" => new xmlrpcval($subject, "string"),
		"lineendings" => new xmlrpcval("unix", "string"),
		"year" => new xmlrpcval(date("Y"), "int"),
		"mon" => new xmlrpcval(date("m"), "int"),
		"day" => new xmlrpcval(date("d"), "int"),
		"hour" => new xmlrpcval(date("G"), "int"),
		"min" => new xmlrpcval(date("i"), "int"),
		), "struct")));

		$res = $this->client->send($m);
		if(!$res->faultCode()) {
			$sv = $res->value()->scalarval();
			$item_id = $sv["itemid"]->scalarval();
			$anum = $sv["anum"]->scalarval();
			$url = $sv["url"]->scalarval();
			
			$item = new LJItem();
			$item->id = $item_id;
			$item->url = $url;
			$item->anum = $anum;
			$item->subject = $subject;
			$item->event = $text;
//			$item->eventtime = sprintf("%s", date());
//			var_dump($item->eventtime);
			
			// TODO fill other fields of a value!
			 
			return $item;
			//return "Item id: {$item_id}, anum: {$anum}, url: {$url}";
			//echo $v->serialize();
		}
		else {
			throw new Exception($res->faultString());
		}
	}

	// Download parts of the user's journal. See also syncitems mode.
	public function getEvents($nevents = 10) {
		$m = new xmlrpcmsg('LJ.XMLRPC.getevents', array(new xmlrpcval(
		array(
		 "username" => new xmlrpcval($this->username, "string"),
		 "password" => new xmlrpcval($this->password, "string"),
		 "ver" => new xmlrpcval("1", "int"), // TODO ver property
		 "noprops" => new xmlrpcval("1", "int"), // TODO parameter
		 "selecttype" => new xmlrpcval("lastn", "string"), // TODO argument
		 "lineendings" => new xmlrpcval("unix", "string"), // TODO property
		 "truncate" => new xmlrpcval("20", "int"), // TODO argument
		 "howmany" => new xmlrpcval($nevents, "int")
		), "struct")));
			
		$res = $this->client->send($m);
		if(!$res->faultCode()) {
			//var_dump($res->value());

			$sv = $res->value()->scalarval();
			$events_sv = $sv["events"]->scalarval();

			$items = array();
			foreach($events_sv as $event) {
				$event_sv = $event->scalarval();
				
				$subject = $event_sv["subject"];
				$allowmask = $event_sv["allowmask"];
				$poster = $event_sv["poster"];
				$props = $event_sv["props"];
				$security = $event_sv["security"];
				$reply_count = $event_sv["reply_count"];
				
				$item = new LJItem();
				$item->id = $event_sv["itemid"]->scalarval();
				$item->anum = $event_sv["anum"]->scalarval();
				$item->url = $event_sv["url"]->scalarval();
				$item->event = $event_sv["event"]->scalarval();
				$item->eventtime = $event_sv["eventtime"]->scalarval();
				if (!empty($subject)) $item->subject = $subject->scalarval();
				if (!empty($allowmask)) $item->allowmask = $allowmask->scalarval();
				if (!empty($poster)) $item->poster = $poster->scalarval();
				if (!empty($props)) $item->props = $props->scalarval();
				if (!empty($security)) $item->security = $security->scalarval();
				if (!empty($reply_count)) $item->replyCount = $reply_count->scalarval();
				$items[] = $item;
			}

			return $items;
		} else {
			throw new Exception($res->faultString());
		}
		throw new Exception("not implemented");
	}

	// Returns a list of which other LiveJournal users this user lists as their friend.
	public function getFriends() {
		throw new Exception("not implemented");
	}

	// Returns a list of which other LiveJournal users list this user as their friend.
	public function friendOf() {
		$m = new xmlrpcmsg('LJ.XMLRPC.getevents', array(new xmlrpcval(
		array(
		 "username" => new xmlrpcval($this->username, "string"),
		 "password" => new xmlrpcval($this->password, "string"),
		 "ver" => new xmlrpcval("1", "int"),
//		 "noprops" => new xmlrpcval("1", "int"),
//		 "selecttype" => new xmlrpcval("lastn", "string"),
//		 "lineendings" => new xmlrpcval("unix", "string"),
//		 "truncate" => new xmlrpcval("20", "int"),
//		 "howmany" => new xmlrpcval($nevents, "int")
		), "struct")));
			
		$res = $this->client->send($m);
	}

	// Retrieves a list of the user's defined tags.
	public function getUserTags() {
		throw new Exception("not implemented");
	}

	// Edit or delete a user's past journal entry
	public function checkFriends() {
		throw new Exception("not implemented");
	}

	// 'consolecommand' - run an administrative command
	public function consoleCommand(){
		throw new Exception("not implemented");
	}

	// Edit or delete a user's past journal entry
	public function editEvent() {
		throw new Exception("not implemented");
	}

	// Edit the user's defined groups of friends.
	public function editFriendGroups() {
		throw new Exception("not implemented");
	}

	// Add, edit, or delete friends from the user's Friends list.
	public function editFriends() {
		throw new Exception("not implemented");
	}

	// Generate a server challenge string for authentication.
	public function getChallenge() {
		throw new Exception("not implemented");
	}

	// This mode retrieves the number of journal entries per day.
	public function getDayCounts() {
		throw new Exception("not implemented");
	}

	// Retrieves a list of the user's defined groups of friends.
	public function getFriendGroups() {
		throw new Exception("not implemented");
	}

	// validate user's password and get base information needed for client to function
	public function login() {
		throw new Exception("not implemented");
	}

	// Expires session cookies.
	public function sessionExpire() {
		throw new Exception("not implemented");
	}

	// Generate a session cookie.
	public function sessionGenerate() {
		throw new Exception("not implemented");
	}

	// Returns a list of all the items that have been created or updated for a user.
	public function syncItems() {
		throw new Exception("not implemented");
	}
}